#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <sys/select.h>
#include <string.h>

// ============== 宏定义 ==============
#define BUF_SIZE 1024

/* Usage: 
 * 先启动服务器，再启动客户机
 * 先关闭客户机，再关闭服务器
 */
#define LOCALIP "192.168.162.128"
#define CLOUDIP_T "47.115.220.165"
#define CLOUDIP_M "47.111.20.8"
#define PORT "9080"

// ============== 宏函数 ==============
#define CHECK_ERROR(cond, msg, cleanup) \
    if(cond) { perror(msg); cleanup; return -1;  }

// ============== 主函数 ==============
int main(int argc, char *argv[]){    
    // 检查句柄返回
    int ret_check = 0;

    // 创建Socket对象：IPv4, TCP
    int socket_fd = socket(AF_INET, SOCK_STREAM, 0);
    CHECK_ERROR(socket_fd < 0, "socket", NULL);

    // 设定服务器端口与IP地址
    struct sockaddr_in serv_addr = {
        .sin_family = AF_INET,
        .sin_port = htons(atoi(PORT))
    };
    if (inet_pton(AF_INET, CLOUDIP_M, &serv_addr.sin_addr) <= 0) {
        perror("invalid address");
        close(socket_fd);
        return -1;
    }

    // 三次握手
    ret_check = connect(socket_fd, (struct sockaddr *)&serv_addr, sizeof(serv_addr));
    CHECK_ERROR(ret_check < 0, "connect failed", close(socket_fd));

    printf("Connected to server %s:%s\n", CLOUDIP_M, PORT);

    // 创建缓冲数组
    fd_set read_fds;
    char sendbuf[BUF_SIZE] = {0};
    char recvbuf[BUF_SIZE] = {0};

    while(1){
        // 设置select监听
        FD_ZERO(&read_fds);                  // 初始化
        FD_SET(socket_fd, &read_fds);        // 监听输出
        FD_SET(STDIN_FILENO, &read_fds);     // 监听标准输入

        // 设置监听，每次等待60s
        struct timeval tv = {60, 0}; 
        int max_fd = (socket_fd > STDIN_FILENO) ? socket_fd : STDIN_FILENO;
        int ret = select(max_fd + 1, &read_fds, NULL, NULL, &tv); // tv是超时标志
        if(ret == 0){
            printf("\rNo data in 60 seconds...\n");
        }
        CHECK_ERROR(ret < 0, "selct error", close(socket_fd));

        // 处理用户输入
        if (FD_ISSET(STDIN_FILENO, &read_fds)) {
            bzero(sendbuf, sizeof(sendbuf));

            ssize_t input_len = read(STDIN_FILENO, sendbuf, sizeof(sendbuf) - 1);
            CHECK_ERROR(input_len <= 0, "read stdin failed", close(socket_fd));

            sendbuf[input_len] = '\0';
            send(socket_fd, sendbuf, input_len, 0);
        }

        // 处理客户端信息
        if(FD_ISSET(socket_fd, &read_fds)){
            bzero(recvbuf, sizeof(recvbuf));

            ssize_t output_len = read(socket_fd, recvbuf, sizeof(recvbuf));
            CHECK_ERROR(output_len <= 0, "Server disconnected", NULL);
            
            recvbuf[output_len] = '\0';
            printf("%s", recvbuf);
        }
    }

    close(socket_fd);
    return 0;
}
